package com.huasan.www.demon.rest.resource;

import java.io.IOException;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.glassfish.jersey.server.mvc.Viewable;
import org.springframework.beans.factory.annotation.Autowired;

import com.huasan.www.demon.data.service.AccountinfoService;
import com.huasan.www.demon.data.service.UserdetailService;
import com.huasan.www.demon.data.service.UserinfoService;
import com.huasan.www.demon.pojo.Accountinfo;
import com.huasan.www.demon.pojo.AccountinfoExample;
import com.huasan.www.demon.pojo.Userdetail;
import com.huasan.www.demon.pojo.UserdetailExample;
import com.huasan.www.demon.pojo.Userinfo;
import com.huasan.www.demon.rest.util.Constants;
import com.huasan.www.demon.util.DataTableUtil;
import com.huasan.www.demon.util.DemonCipher;
import com.huasan.www.demon.util.Des;
import com.huasan.www.demon.util.OnePage;

@Path("/account")
public class AccountInfoResource extends Resource{

	@Autowired
	private AccountinfoService accountinfoService;
	
	@Autowired
	private UserdetailService userdetailService;
	
	@Autowired
	private UserinfoService userinfoService;
	
	private Accountinfo accountinfo;
	
	private static Random random = new Random();
	
	@GET
	@Produces("text/html")
	public Viewable getMain(){
		return getView("account", null);
	}
	
	@GET
	@Path("/add")
	@Produces("text/html")
	public Viewable getAdd(){
		return getView("account_edit", null);
	}
	
	@GET
	@Path("/edit")
	@Produces("text/html")
	public Viewable getEdit(@QueryParam("id") Integer id) {
		Map ret = new HashMap(); 
		ret.put("edit", "true");
		accountinfo = accountinfoService.selectByPrimaryKey(id.longValue());
		return getView( "account_edit", this,  ret );
	}
	
	@POST
	@Path("/accounts")
	@Produces({MediaType.APPLICATION_JSON} )
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public String getAccounts(@FormParam("sEcho") String sEcho,
			@FormParam("iDisplayStart") Integer iDisplayStart,
			@FormParam("iDisplayLength") Integer iDisplayLength,
			@FormParam("sSearch") String sSearch,
			@FormParam("loginname") String loginname,
			@FormParam("optcode") String optcode
				) throws JsonGenerationException, JsonMappingException, IOException{
		AccountinfoExample example = new AccountinfoExample();
		example.setOrderByClause("status desc, actived");
		AccountinfoExample.Criteria criteria = example.createCriteria();
		if (loginname!=null)
			criteria.andLoginnameLike(DataTableUtil.wrapLike( loginname ));
		if (optcode!=null)
			criteria.andOptcodeLike(DataTableUtil.wrapLike( optcode ));
		Integer total = accountinfoService.countByExample(example);
		example.setLimitStart(iDisplayStart);
		example.setLimitEnd(iDisplayLength);
		OnePage<Accountinfo> page = accountinfoService.selectOnePageByExample(example);
		return DataTableUtil.getDataTable(sEcho, total, total
				, objectmapper.writeValueAsString(page.getDataList()));
	}
	
	@DELETE
	@Path("/delete")
	@Produces({MediaType.APPLICATION_JSON} )
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public String deleteAccount(@FormParam("ids") List<Integer> ids) {
		try{
			for (Integer id : ids){
				accountinfoService.deleteByPrimaryKey(id.longValue());
			}
			return getSucReturn("");
		}catch (Exception e){
			logger.error(e.getMessage(), e);
			return getErrReturn("");
		}
	}
	
	@PUT
	@Path("/addaccount")
	@Produces({MediaType.APPLICATION_JSON} )
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public String addAccount(@FormParam(value = "loginname") String loginname,
			@FormParam(value = "pwd") String pwd,
			@FormParam(value = "optcode")String optcode,
			@FormParam(value = "actived")String actived
			){
		try{
			if (loginnameExisted(loginname))
				return getErrReturn("用户已存在");
			
			Accountinfo accountinfo = new Accountinfo();
			accountinfo.setLoginname(loginname);
			accountinfo.setPwd(pwd);
			accountinfo.setOptcode(optcode);
			accountinfo.setActived(actived);
			accountinfoService.insertSelective(accountinfo);
			return getSucReturn("保存成功"); 
		}catch (Exception e){
			logger.error(e.getMessage(), e);
			return getErrReturn("保存失败，请重试");
		}
	}
	
	@PUT
	@Path("/saveaccount")
	@Produces({MediaType.APPLICATION_JSON} )
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public String saveAccount(@FormParam(value = "id") Integer id,
			@FormParam(value = "loginname") String loginname,
			@FormParam(value = "pwd") String pwd,
			@FormParam(value = "optcode")String optcode,
			@FormParam(value = "actived")String actived
			){
		try{
			Accountinfo accountinfo = accountinfoService.selectByPrimaryKey(id.longValue());
			accountinfo.setPwd(pwd);
			accountinfo.setOptcode(optcode);
			accountinfo.setActived(actived);
			accountinfoService.updateByPrimaryKey(accountinfo);
			return getSucReturn("保存成功"); 
		}catch (Exception e){
			logger.error(e.getMessage(), e);
			return getErrReturn("保存失败，请重试");
		}
	}
	
	private boolean loginnameExisted(String loginname){
		AccountinfoExample example = new AccountinfoExample();
		AccountinfoExample.Criteria criteria = example.createCriteria();
		criteria.andLoginnameEqualTo(loginname);
		return accountinfoService.countByExample(example)>0;
	}
	
	@GET
	@Path("/set")
	@Produces( {MediaType.APPLICATION_JSON} )
	public String mGetAccount(@QueryParam("opt") String opt, @HeaderParam("userId") Integer id){
		try{
			String[] opts = opt.split(",");
			int i = 0;
			Accountinfo accountinfo=null;
			for ( i=0 ; i<opts.length; i++){
				accountinfo = getAccountByOptCode(opts[i], Constants.POOL_SIZE);
				if (accountinfo!=null)
					break;
			}
			if (accountinfo == null)
				return getErrReturn("无可用账户");
			else {
				Userinfo info = userinfoService.selectByPrimaryKey(id.longValue());
				updateStatus(info, accountinfo);
				DemonCipher des = new Des();
				String pwd = des.encrypt(info.getSid(), accountinfo.getPwd());
				return getSucReturn("{\"opt\": \""+opts[i]+"\", \"id\": \""+accountinfo.getId()
						+ "\", \"name\": \""+accountinfo.getLoginname()+"\", \"pwd\": \""+pwd+"\"}", "");
			}
		}catch (Exception e){
			logger.error(e.getMessage(), e);
			return getErrReturn("获取失败");
		}
	}
	
	@GET
	@Path("/on")
	@Produces( {MediaType.APPLICATION_JSON} )
	public String mLoginAccount(@QueryParam("id") Integer accountId, @HeaderParam("userId") Integer id){
		try{
			UserdetailExample example = new UserdetailExample();
			UserdetailExample.Criteria creteria = example.createCriteria();
			creteria.andUseridEqualTo(id.longValue());
			creteria.andAccountidEqualTo(accountId.longValue());
			creteria.andChargetimeIsNull();
			creteria.andEndtimeIsNull();
			example.setOrderByClause(" logintime desc ");
			List<Userdetail> list = userdetailService.selectByExample(example);
			if (list.size()==0){
				updateStatus(id, accountId);
				return getErrReturn("无用户记录");
			} else {
				Userdetail userdetail = list.get(0);
				Timestamp date = new Timestamp(System.currentTimeMillis());
				userdetail.setAlivetime(date);
				userdetail.setChargetime(date);
				userdetail.setStatus("1");
				userdetailService.updateByPrimaryKey(userdetail);
				return getSucReturn("\"\"", "开始计时");
			}
		}catch (Exception e){
			logger.error(e.getMessage(), e);
			return getErrReturn("信息更新失败");
		}
	}
	
	@GET
	@Path("/alive")
	@Produces( {MediaType.APPLICATION_JSON} )
	public String mAliveAccount(@QueryParam("id") Integer accountId, @HeaderParam("userId") Integer id){
		try{
			UserdetailExample example = new UserdetailExample();
			UserdetailExample.Criteria creteria = example.createCriteria();
			creteria.andUseridEqualTo(id.longValue());
			creteria.andUseridEqualTo(id.longValue());
			creteria.andChargetimeIsNotNull();
			creteria.andEndtimeIsNull();
			example.setOrderByClause(" chargetime desc ");
			List<Userdetail> list = userdetailService.selectByExample(example);
			if (list.size()==0){
				updateStatus(id);
				return getErrReturn("无用户记录");
			} else {
				Userdetail userdetail = list.get(0);
				userdetail.setAlivetime(new Timestamp(System.currentTimeMillis()));
				userdetailService.updateByPrimaryKey(userdetail);
				return getSucReturn("\"\"", "保持登录");
			}
		}catch (Exception e){
			logger.error(e.getMessage(), e);
			return getErrReturn("信息更新失败");
		}
	}
	
	@GET
	@Path("/off")
	@Produces( {MediaType.APPLICATION_JSON} )
	public String mOffAccount(@QueryParam("id") Integer accountId, @HeaderParam("userId") Integer id){
		try{
			UserdetailExample example = new UserdetailExample();
			UserdetailExample.Criteria creteria = example.createCriteria();
			creteria.andUseridEqualTo(id.longValue());
			creteria.andChargetimeIsNotNull();
			//creteria.andEndtimeIsNull();
			example.setOrderByClause(" chargetime desc, logintime desc ");
			List<Userdetail> list = userdetailService.selectByExample(example);
			if (list.size()==0){
				/* 
				if (accountId!=null){
					Accountinfo accountinfo = accountinfoService.selectByPrimaryKey(accountId.longValue());
					accountinfo.setStatus("0");
					accountinfo.setCuruser(null);
					accountinfoService.updateByPrimaryKey(accountinfo);
				}
				*/
				updateEndStatus(id, accountId);
				return getErrReturn("无用户记录");
			} else {
				Userdetail userdetail = list.get(0);
				Long accId;
				try{
					accId = Long.valueOf(accountId);
				}catch (Exception e){
					logger.error("Invalidate AccountId From Client");
					accId = userdetail.getAccountid();
				}
				Accountinfo accountinfo = accountinfoService.selectByPrimaryKey(accId);
				accountinfo.setStatus("0");
				accountinfo.setCuruser(null);
				accountinfoService.updateByPrimaryKey(accountinfo);
				
				Timestamp date = new Timestamp(System.currentTimeMillis());
				userdetail.setAlivetime(date);
				userdetail.setEndtime(date);
				userdetail.setStatus("2");
				userdetailService.updateByPrimaryKey(userdetail);
				return getSucReturn("\"\"", "帐号释放");
			}
		}catch (Exception e){
			logger.error(e.getMessage(), e);
			return getErrReturn("信息更新失败");
		}
	}
	
	private void updateEndStatus(Integer id, Integer acountId) {
		if (acountId!=null){
			Accountinfo accountinfo = accountinfoService.selectByPrimaryKey(acountId.longValue());
			accountinfo.setStatus("0");
			accountinfo.setCuruser(null);
			accountinfoService.updateByPrimaryKey(accountinfo);
		}
		Timestamp date = new Timestamp(System.currentTimeMillis());
		updateStatus(id, null, date, null, date, date);
	}

	private void updateStatus(Integer userid) {
		Timestamp date = new Timestamp(System.currentTimeMillis());
		updateStatus(userid, null, date, date, date, null);
	}
	
	private void updateStatus(Integer userid, Integer accountId) {
		Accountinfo accountinfo = accountinfoService.selectByPrimaryKey(accountId.longValue());
		Timestamp date = new Timestamp(System.currentTimeMillis());
		updateStatus(userid, accountinfo, date, date, date, null);
	}
	
	private void updateStatus(Userinfo userinfo, Accountinfo accountinfo) {
		Timestamp date = new Timestamp(System.currentTimeMillis());
		updateStatus(userinfo, accountinfo, date,  null, date, null);
	}
	
	private void updateStatus(Integer userid, Accountinfo accountinfo) {
		Timestamp date = new Timestamp(System.currentTimeMillis());
		updateStatus(userid, accountinfo, date,  null, date, null);
	}
	
	private void updateStatus(Integer userid, Accountinfo accountinfo, Timestamp logintime, Timestamp chargeTime, Timestamp liveTime, Timestamp endTime) {
		Userdetail userdetail = new Userdetail();
		userdetail.setUserid(userid.longValue());
//		userdetail.setMobileno(mobileno);
		if (accountinfo!=null){
			userdetail.setAccountid(accountinfo.getId());
			userdetail.setOptcode(accountinfo.getOptcode());
		}
		userdetail.setStatus("0");
		if (logintime!=null){
			userdetail.setLogintime(logintime);
		}
		if (chargeTime!=null){
			userdetail.setChargetime(chargeTime);
			userdetail.setStatus("1");
		}
		if (liveTime!=null){
			userdetail.setAlivetime(liveTime);
		}
		if (endTime!=null){
			userdetail.setEndtime(endTime);
			userdetail.setStatus("2");
		}
		userdetailService.insertSelective(userdetail);
		
		if (accountinfo!=null){
			accountinfo.setStatus("1");
			try{
				Userinfo user = userinfoService.selectByPrimaryKey(userid.longValue());
				if (user!=null)
					accountinfo.setCuruser(user.getLoginname());
			}catch (Exception e){
				logger.error(e.getMessage(),e);
			}
			accountinfoService.updateByPrimaryKey(accountinfo);
		}
	}
	
	private void updateStatus(Userinfo userinfo, Accountinfo accountinfo, Timestamp logintime, Timestamp chargeTime, Timestamp liveTime, Timestamp endTime) {
		Userdetail userdetail = new Userdetail();
		userdetail.setUserid(userinfo.getId().longValue());
		userdetail.setMobileno(userinfo.getMobileno());
		if (accountinfo!=null){
			userdetail.setAccountid(accountinfo.getId());
			userdetail.setOptcode(accountinfo.getOptcode());
		}
		userdetail.setStatus("0");
		if (logintime!=null){
			userdetail.setLogintime(logintime);
		}
		if (chargeTime!=null){
			userdetail.setChargetime(chargeTime);
			userdetail.setStatus("1");
		}
		if (liveTime!=null){
			userdetail.setAlivetime(liveTime);
		}
		if (endTime!=null){
			userdetail.setEndtime(endTime);
			userdetail.setStatus("2");
		}
		userdetailService.insertSelective(userdetail);
		
		if (accountinfo!=null){
			accountinfo.setStatus("1");
			accountinfo.setCuruser(userinfo.getLoginname());
			accountinfoService.updateByPrimaryKey(accountinfo);
		}
	}

	private Accountinfo getAccountByOptCode(String code, Integer poolSize){
		AccountinfoExample example = new AccountinfoExample();
		example.setLimitStart(0);
		example.setLimitEnd(poolSize);
		AccountinfoExample.Criteria criteria = example.createCriteria();
		criteria.andOptcodeEqualTo(code);
		criteria.andActivedEqualTo("1");
		criteria.andStatusEqualTo("0");
		OnePage<Accountinfo> onepage = accountinfoService.selectOnePageByExample(example);
		if (onepage.getDataList().size()==0)
			return null;
		return onepage.getDataList().get(random.nextInt(onepage.getDataList().size()));
	}
	
	public Accountinfo getAccountinfo() {
		return accountinfo;
	}

	public void setAccountinfo(Accountinfo accountinfo) {
		this.accountinfo = accountinfo;
	}
	
}
